package com.funtl.screw.auth.service;

import com.funtl.screw.common.core.constant.SecurityConstants;
import lombok.Cleanup;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
import org.springframework.stereotype.Service;

/**
 * 授权码模式
 *
 * @author lusifer
 */
@Service
@RequiredArgsConstructor
public class ServiceAuthorizationCodeServicesImpl extends RandomValueAuthorizationCodeServices {

    @Value("${service.authorizationCode.expirationTime:300}")
    private Long expirationTime;

    private final RedisConnectionFactory connectionFactory;

    @Setter
    private String prefix = SecurityConstants.SERVICE_PREFIX + SecurityConstants.OAUTH_CODE_PREFIX;

    @Setter
    private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();

    /**
     * 保存 code 和 认证信息
     */
    @Override
    protected void store(String code, OAuth2Authentication authentication) {
        @Cleanup
        RedisConnection connection = connectionFactory.getConnection();
        connection.set(serializationStrategy.serialize(prefix + code), serializationStrategy.serialize(authentication), Expiration.seconds(expirationTime), RedisStringCommands.SetOption.UPSERT);
    }

    /**
     * 删除code 并返回认证信息
     */
    @Override
    protected OAuth2Authentication remove(String code) {
        @Cleanup
        RedisConnection connection = connectionFactory.getConnection();
        byte[] key = serializationStrategy.serialize(prefix + code);
        byte[] value = connection.get(key);
        if (value == null) {
            return null;
        }
        OAuth2Authentication oAuth2Authentication = serializationStrategy.deserialize(value, OAuth2Authentication.class);
        connection.del(key);
        return oAuth2Authentication;
    }

}